#if js
import js.Dom;
#else true
private typedef HtmlDom = Dynamic
#end

import hxbase.publicapi.googlemaps.GoogleMaps;

extern class GEvent
{
	static public function addListener(source:Dynamic, event:String, handler:Dynamic) : GEventListener;
	static public function addDomListener(source:Dynamic, event:String, handler:Dynamic) : GEventListener;
	static public function removeListener(handle:GEventListener) : Void;
	static public function clearInstanceListeners(source:Dynamic) : Void;
}

extern class GEventListener {}

extern class GOverlay // Google class this an interface, but its more like an abstract class...
{
	static public function getZIndex(latitude:Int):Int;
	
	public function new():Void;
	
	public function initialize(map:Map2):Void;
	public function remove():Void;
	public function copy():Void;
	public function redraw(force:Bool):Void;
}

extern class GMap2
{
	public function new(container : HtmlDom, ?opts : MapOptions) : Void;
	
	public function enableDragging() : Void;
	public function disableDragging() : Void;
	public function draggingEnabled() : Bool;
	public function enableInfoWindow() : Void;
	public function disableInfoWindow() : Void;
	public function infoWindowEnabled() : Bool;
	public function enableDoubleClickZoom() : Void;
	public function disableDoubleClickZoom() : Void;
	public function doubleClickZoomEnabled() : Bool;
	public function enableContinuousZoom() : Void;
	public function disableContinuousZoom() : Void;
	public function continuousZoomEnabled() : Bool;
	public function enableScrollWheelZoom() : Void;
	public function disableScrollWheelZoom() : Void;
	public function scrollWheelZoomEnabled() : Bool;
	
	public function addControl(control : Control,  ?position : ControlPosition) : Void;
	public function removeControl(control : Control) : Void;
	public function getContainer() : HtmlDom;
	
	public function getMapTypes() : Array<MapType>;
	public function getCurrentMapType() : MapType;
	public function setMapType(type : MapType) : Void;
	public function addMapType(type : MapType) : Void;
	public function removeMapType(type : MapType) : Void;
	
	public function isLoaded() : Bool;
	public function getCenter() : LatLng;
	public function getBounds() : LatLngBounds;
	public function getBoundsZoomLevel(bounds : LatLngBounds) : Int;
	public function getSize() : Size;
	public function getZoom() : Int;
	
	public function setCenter( center : LatLng, ?zoom : Int, ?type : MapType ) : Void;
	public function panTo(center : LatLng) : Void;
	public function panBy(distance : Size) : Void;
	public function panDirection(dx : Int, dy : Int) : Void;
	public function setZoom(level : Int) : Void;
	public function zoomIn() : Void;
	public function zoomOut() : Void;
	public function savePosition() : Void;
	public function returnToSavedPosition() : Void;
	public function checkResize() : Void;
	
	public function addOverlay(overlay : Overlay) : Void;
	public function removeOverlay(overlay : Overlay) : Void;
	public function clearOverlays() : Void;
	public function getPane(pane:MapPane) : HtmlDom;
	
	public function openInfoWindow(point : LatLng,  node : HtmlDom, ?opts : InfoWindowOptions) : Void;
	public function openInfoWindowHtml(point : LatLng, html : String, ?opts : InfoWindowOptions) : Void;
	public function openInfoWindowTabs(point : LatLng, tabs : Array<InfoWindowTab>, ?opts : InfoWindowOptions) : Void;
	public function openInfoWindowTabsHtml(point : LatLng, tabs : Array<InfoWindowTab>, ?opts : InfoWindowOptions) : Void;
	public function showMapBlowup(point : LatLng, ?opts : InfoWindowOptions) : Void;
	public function updateInfoWindow(tabs : Array<InfoWindowTab>, ?onupdate : Void -> Void) : Void;
	public function updateCurrentTab(modifier : InfoWindowTab -> Void, ?onupdate : Void -> Void) : Void;
	public function closeInfoWindow() : Void;
	public function getInfoWindow() : InfoWindow;
	public function fromLatLngToDivPixel(latlng : LatLng) : Point;
	public function fromDivPixelToLatLng(pixel : Point) : LatLng;
	public function fromContainerPixelToLatLng(pixel : Point) : LatLng;
}

extern class GInfoWindowTab
{
	public function new(label : String, content : Dynamic) : Void;
}

extern class GMarker extends GOverlay
{
	public function new(latlng : LatLng, ?opts : MarkerOptions) : Void;
	public function openInfoWindow(content:HtmlDom, ?opts:InfoWindowOptions) : Void;
	public function openInfoWindowHtml(content:String, ?opts:InfoWindowOptions) : Void;
	public function openInfoWindowTabs(tabs:Array<InfoWindowTab>, ?opts:InfoWindowOptions) : Void;
	public function openInfoWindowTabsHtml(tabs:Array<InfoWindowTab>, ?opts:InfoWindowOptions) : Void;
	public function showMapBlowup(?opts:InfoWindowOptions) : Void;
	public function getIcon() : Icon;
	public function getPoint() : LatLng;
	public function setPoint(point:LatLng) : Void;
	public function enableDragging() : Void;
	public function disableDragging() : Void;
	public function draggable() : Bool;
	public function draggingEnabled() : Bool;
	public function setImage(url:String) : Void;
	public function hide() : Void;
	public function show() : Void;
	public function isHidden() : Bool;
}

extern class GPolyline extends GOverlay
{
	static public function fromEncoded(color:Null<String>, weight:Null<Int>, opacity:Null<Float>, points:String, zoomFactor:Int, levels:String, numLevels:Int) : Polyline;
	public function new(points:Array<LatLng>, color:String, weight:Int, opacity:Float) : Void;
	public function getVertexCount() : Int;
	public function getVertex(index : Int) : LatLng;
}

extern class GPolygon
{
	static public function fromEncoded(polylines:Array<String>,  ?fill:Bool,  ?color:String,  ?opacity:Float,  ?outline:Bool) : Polygon;
	public function new(points:Array<LatLng>, strokeColor:String,  strokeWeight:Int,  strokeOpacity:Float,  fillColor:String,  fillOpacity:Float) : Void;
	public function getVertexCount() : Int;
	public function getVertex(index : Int) : LatLng;
}

extern class GGroundOverlay
{
	public function new(imageUrl:String, bounds:LatLngBounds) : Void;
}

extern class GIcon
{
	static public var G_DEFAULT_ICON:Icon;
	
	public function new(?copy:Icon, ?image:String) : Void;
	
	public var image : String;
	public var shadow : String;
	public var iconSize : Size;
	public var shadowSize : Size;
	public var iconAnchor : Point;
	public var infoWindowAnchor : Point;
	public var printImage : String;
	public var mozPrintImage : String;
	public var printShadow : String;
	public var transparent : String;
	public var imageMap : Array<Int>;
	public var maxHeight : Int;
	public var dragCrossImage : String;
	public var dragCrossSize : Size;
	public var dragCrossAnchor : Point;
}

extern class GPoint
{
	public function new(x:Int,y:Int) : Void;
	public var x : Int;
	public var y : Int;
	public function equals(point:Point) : Bool;
	public function toString() : String;
}

extern class GSize
{
	public function new(width:Float, height:Float) : Void;

	public var width(default, null) : Float;
	public var height(default, null) : Float;
	
	public function equals(other:Size) : Bool;
	public function toString() : String;
}

extern class GLatLng
{
	public function new(lat:Float, lng:Float, ?unbounded:Bool) : Void;
	
	public function lat() : Float;
	public function lng() : Float;
	public function latRadians() : Float;
	public function lngRadians() : Float;
	public function equals(latlng:LatLng) : Bool;
	public function distanceFrom(latlng:LatLng) : Float;
	public function toUrlValue(?precision:Int) : String;
}

extern class GLatLngBounds
{
	public function new(southWest:LatLng, northEast:LatLng) : Void;
	public function equals(other:LatLngBounds) : Bool;
	public function contains(latlng:LatLng) : Bool;
	public function intersects(other:LatLngBounds) : Bool;
	public function containsBounds(other:LatLngBounds) : Bool;
	public function extend(latlng:LatLng) : Void;
	public function getSouthWest() : LatLng;
	public function getNorthEast() : LatLng;
	public function toSpan() : LatLng;
	public function isFullLat() : Bool;
	public function isFullLng() : Bool;
	public function isEmpty() : Bool;
	public function getCenter() : LatLng;
}

extern class GControlPosition
{
	public function new(anchor:GControlAnchor, offset:Size) : Void;
}

extern class GMapType
{
	/*
	public static var G_NORMAL_MAP : MapType;
	public static var G_SATELLITE_MAP : MapType;
	public static var G_HYBRID_MAP : MapType;
	public static var G_DEFAULT_MAP_TYPES : Array<MapType>;
	*/
	
	public function new(layers:Array<TileLayer>, projection:Projection, name:String, ?opts:MapTypeOptions) : Void;
	
	public function getSpanZoomLevel(center:LatLng, span:LatLng, viewSize:Size) : Int;
	public function getBoundsZoomLevel(bounds:LatLngBounds, viewSize:Size) : Void;
	public function getName(opt_short:Bool) : String;
	public function getProjection() : Projection;
	public function getTileSize() : Int;
	public function getTileLayers() : Array<TileLayer>;
	public function getMinimumResolution(?latlng:LatLng) : Int;
	public function getMaximumResolution(?latlng:LatLng) : Int;
	public function getTextColor() : String;
	public function getLinkColor() : String;
	public function getErrorMessage() : String;
	public function getCopyrights(bounds:LatLngBounds, zoom:Int) : Array<String>;
	public function getUrlArg() : String;
}

extern class GMapPane
{
/*	static public var G_MAP_MAP_PANE : Dynamic;
	static public var G_MAP_MARKER_SHADOW_PANE : Dynamic;
	static public var G_MAP_MARKER_PANE : Dynamic;
	static public var G_MAP_FLOAT_SHADOW_PANE : Dynamic;
	static public var G_MAP_MARKER_MOUSE_TARGET_PANE : Dynamic;
	static public var G_MAP_FLOAT_PANE : Dynamic;
*/
}

extern class GControlAnchor
{
/*	static public var G_ANCHOR_TOP_RIGHT : Dynamic;
	static public var G_ANCHOR_TOP_LEFT : Dynamic;
	static public var G_ANCHOR_BOTTOM_RIGHT : Dynamic;
	static public var G_ANCHOR_BOTTOM_LEFT : Dynamic;
*/
}

extern class GTileLayer
{
	public function new(copyrights:CopyrightCollection, minResolution:Int, maxResolution:Int) : Void;
	
	public function minResolution() : Int;
	public function maxResolution() : Int;
	public function getTileUrl(tile:Point, zoom:Int) : String;
	public function isPng() : Bool;
	public function getOpacity() : Float;
}

extern interface GProjection
{
	public function fromLatLngToPixel(latlng:LatLng,  zoom:Int) : Point;
	public function fromPixelToLatLng(pixel:Point, zoom:Int, ?unbounded:Bool) : Void;
	public function tileCheckRange(tile:Point, zoom:Int, tilesize:Int) : Void;
	public function getWrapWidth(zoom:Int) : Void;
}

extern class GCopyrightCollection
{
	public function new(prefix:String) : Void;
	public function addCopyright(copyright:Copyright) : Void;
	public function getCopyrights(bounds:LatLngBounds, zoom:Int) : Array<String>;
	public function getCopyrightNotice(bounds:LatLngBounds, zoom:Int) : String;
}

extern class GCopyright
{
	public function new(id : Int, bounds : LatLngBounds, minZoom : Int, text : String) : Void;
	
	public var id : Int;
	public var minZoom : Int;
	public var bounds : LatLngBounds;
	public var text : String;
}

extern class GControl
{
	public function new(?printable:Bool, ?selectable:Bool) : Void;
	
	public function printable() : Bool;
	public function selectable() : Bool;
	public function initialize(map:Map2) : HtmlDom;
	public function getDefaultPosition() : ControlPosition;
}

extern class GSmallMapControl		extends GControl {}
extern class GLargeMapControl		extends GControl {}
extern class GSmallZoomControl		extends GControl {}
extern class GScaleControl			extends GControl {}
extern class GMapTypeControl		extends GControl {}
extern class GOverviewMapControl	extends GControl {}

extern class GDirections
{
	public function new(?map:Map2, ?panel:HtmlDom) : Void;
	
	public function load(query:String, ?queryOpts:DirectionsOptions) : Void;
	public function loadFromWaypoints(waypoints:Array<Dynamic>, ?queryOpts:DirectionsOptions ) : Void;
	public function clear() : Void;
	public function getStatus() : { code: Int, request : String };
	public function getBounds() : LatLngBounds;
	public function getNumRoutes() : Int;
	public function getRoute(i:Int) : Route;
	public function getNumGeocodes() : Int;
	public function getGeocode(i:Int) : Dynamic;
	public function getCopyrightsHtml() : String;
	public function getSummaryHtml() : String;
	public function getDistance() : { meters:Float,  html:String };
	public function getDuration() : { seconds:Float, html:String };
	public function getPolyline() : Polyline;
	public function getMarker(i:Int) : Marker;
}

extern class GRoute
{
	public function getNumSteps() : Int;
	public function getStep(i:Int) : Step;
	public function getStartGeocode() : Dynamic;
	public function getEndGeocode() : Dynamic;
	public function getEndLatLng() : LatLng;
	public function getSummaryHtml() : String;
	public function getDistance() : { meters:Float,  html:String };
	public function getDuration() : { seconds:Float, html:String };
}

extern class GStep
{
	public function getLatLng() : LatLng;
	public function getPolylineIndex() : Int;
	public function getDescriptionHtml() : String;
	public function getDistance() : { meters:Float,  html:String };
	public function getDuration() : { seconds:Float, html:String };
}

extern class GMarkerManager
{
	public function new(map:Map2, ?opts:MarkerManagerOptions) : Void;
	public function addMarkers(markers:Array<Marker>, minZoom:Int, ?maxZoom:Int) : Void;
	public function addMarker(marker:Marker, minZoom:Int, ?maxZoom:Int) : Void;
	public function refresh() : Void;
	public function getMarkerCount(zoom:Int) : Int;
}

extern class GBounds
{
	public function new(points:Array<Point>) : Void;
	
	public var minX(default,null) : Int;
	public var minY(default,null) : Int;
	public var maxX(default,null) : Int;
	public var maxY(default,null) : Int;
	
	public function toString() : String;
	public function min() : Point;
	public function max() : Point;
	public function containsBounds(other:Bounds) : Bool;
	public function extend(point:Point) : Void;
	public function intersection(other:Bounds) : Bounds;
}